package com.electric.electric.serviceimpl;

import com.electric.electric.POJO.DTO.EvaluationRequestDTO;
import com.electric.electric.POJO.DTO.SecondaryIndicatorDTO;
import com.electric.electric.POJO.Entity.Evaluation;
import com.electric.electric.POJO.VO.EvaluationResponseVO;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.electric.electric.mapper.EvaluationMapper;
import com.electric.electric.service.EvaluationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class EvaluationServiceImpl implements EvaluationService {

    @Autowired(required = false)
    private EvaluationMapper evaluationMapper;

    @Autowired
    private ObjectMapper objectMapper;

    private final List<ValuationRange> valuationRanges = List.of(
            new ValuationRange(0.85, 1.0, "A", 0.85),
            new ValuationRange(0.70, 0.85, "B", 0.60),
            new ValuationRange(0.50, 0.70, "C", 0.30),
            new ValuationRange(0.30, 0.50, "D", 0.15),
            new ValuationRange(0.10, 0.30, "E", 0.10),
            new ValuationRange(0.000001, 0.10, "F", 0.05)
    );

    private final List<String> negativeIndicators = List.of("运行时长 (B6)", "故障率 (B7)", "缺陷率 (B8)");
    private final List<String> percentageIndicators = List.of("故障率 (B7)", "缺陷率 (B8)", "市场占有率 (B9)");

    @Override
    public EvaluationResponseVO calculateEvaluation(EvaluationRequestDTO request) {
        Map<String, Double> scores = request.getScores();
        List<SecondaryIndicatorDTO> indicators = request.getSecondaryIndicators();
        double originalPrice = request.getOriginalPrice();
        Map<String, Double> primaryIndicatorWeights = request.getPrimaryIndicatorWeights();

        Map<String, Double> normalizedValues = new HashMap<>();
        Map<String, Double> weightedScores = new HashMap<>();
        double totalScore = 0;
        String grade = null;
        Double finalValuation = null;
        Double finalRealPrice = null;

        for (SecondaryIndicatorDTO indicator : indicators) {
            Double Xi = scores.get(indicator.getName());
            double Xmin = indicator.getMin();
            double Xmax = indicator.getMax();

            if (Xi != null) {
                double normalizedValue;
                boolean isNegativeIndicator = negativeIndicators.contains(indicator.getName());

                double measuredValue = Xi;
                double minValue = indicator.getMin();
                double maxValue = indicator.getMax();

                if (percentageIndicators.contains(indicator.getName())) {
                    measuredValue /= 100;
                    minValue /= 100;
                    maxValue /= 100;
                }

                // 公式一：正向指标归一化
                if (!isNegativeIndicator) {
                    normalizedValue = (measuredValue - minValue) / (maxValue - minValue);
                }
                // 公式二：负向指标归一化
                else {
                    normalizedValue = 1 - (measuredValue - minValue) / (maxValue - minValue);
                }
                normalizedValues.put(indicator.getName(), normalizedValue);

                // 公式三：加权求和
                double weightedScore = normalizedValue * indicator.getWeightedWeight();
                weightedScores.put(indicator.getName(), weightedScore);
                totalScore += weightedScore;
            }
        }

        totalScore = Math.max(0, Math.min(1, totalScore));
        totalScore = Math.round(totalScore * 10000.0) / 10000.0; // 保留 4 位小数

        if (totalScore == 0) {
            grade = "建议报废";
            finalRealPrice = 0.0;
        } else {
            for (ValuationRange range : valuationRanges) {
                if (totalScore >= range.getMin() && totalScore < range.getMax()) {
                    grade = range.getGrade();
                    finalRealPrice = originalPrice * range.getPercentage();
                    break;
                } else if (range.getMax() == 1 && totalScore >= range.getMin() && totalScore <= range.getMax()) {
                    grade = range.getGrade();
                    finalRealPrice = originalPrice * range.getPercentage();
                    break;
                }
            }
            if (grade == null) {
                grade = "未评级";
            }
        }

        finalRealPrice = Math.round(finalRealPrice * 10000.0) / 10000.0; // 保留 4 位小数
        finalValuation = totalScore * originalPrice;
        finalValuation = Math.round(finalValuation * 10000.0) / 10000.0; // 保留 4 位小数


        EvaluationResponseVO response = new EvaluationResponseVO();
        response.setNormalizedValues(normalizedValues);
        response.setWeightedScores(weightedScores);
        response.setTotalScore(totalScore);
        response.setGrade(grade);
        response.setFinalValuation(finalValuation);
        response.setFinalRealPrice(finalRealPrice);

        // Save evaluation record using MyBatis-Plus
        if (evaluationMapper != null) {
            Evaluation evaluation = new Evaluation();
            try {
                evaluation.setScoresJson(objectMapper.writeValueAsString(request.getScores()));
                evaluation.setNormalizedValuesJson(objectMapper.writeValueAsString(normalizedValues));
                evaluation.setWeightedScoresJson(objectMapper.writeValueAsString(weightedScores));
                evaluation.setTotalScore(totalScore);
                evaluation.setGrade(grade);
                evaluation.setFinalValuation(finalValuation);
                evaluation.setFinalRealPrice(finalRealPrice);
                evaluation.setEvaluationTime(LocalDateTime.now());
                evaluationMapper.insert(evaluation); // Use MyBatis-Plus insert method
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }

        return response;
    }

    private static class ValuationRange {
        private double min;
        private double max;
        private String grade;
        private double percentage;

        public ValuationRange(double min, double max, String grade, double percentage) {
            this.min = min;
            this.max = max;
            this.grade = grade;
            this.percentage = percentage;
        }

        public double getMin() {
            return min;
        }

        public double getMax() {
            return max;
        }

        public String getGrade() {
            return grade;
        }

        public double getPercentage() {
            return percentage;
        }
    }
}